package com.example.javabasic.elasticsearch.connect;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @description es 链接
 * 文档 https://www.elastic.co/guide/cn/elasticsearch/guide/current/_more_complicated_searches.html
 * api 文档: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-supported-apis.html
 * 中文 api 文档 https://www.cnblogs.com/reycg-blog/p/9931482.html#index-api
 * es原理: https://blog.csdn.net/weixin_41947378/article/details/109405386
 * es 介绍及使用 图形化界面 :https://blog.csdn.net/weixin_40449300/article/details/103972407
 * es 搜索 示例代码  : https://blog.csdn.net/wwwdc1012/article/details/82050655
 * <p>
 * es 搜索文档 : https://www.cnblogs.com/zeenzhou/p/11497948.html
 * @Author Lin FuYuan
 * @date 2021/6/8
 */
public class EsConnect {
    public static void main(String[] args) {
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        HttpHost.create("http://172.24.115.18:9200")
//                        HttpHost.create("http://172.24.115.19:9200"),
//                        HttpHost.create("http://172.24.115.25:9200")
                )
        );
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        String format1 = format.format(date);
        System.out.println(format1);
        try {



//        put(client);
//        get(client);
//            search(client);
            QueryLogDTO dto = new QueryLogDTO();

            dto.setClusterId(70L);
            dto.setLogLevel("INFO");
            dto.setKeyWorld("1023356");
            dto.setPageNum(1);
            dto.setPageSize(4);
            dto.setServerId(1L);
            dto.setServerName("Zookeeper");
            SearchResponse search = client.search(query(dto), RequestOptions.DEFAULT);
            TotalHits totalHits = search.getHits().getTotalHits();
            Iterator<SearchHit> iterator = search.getHits().iterator();
            //遍历获取数据
            List<ServiceLog> list = new ArrayList<>();

            while(iterator.hasNext()){
                SearchHit next = iterator.next();
                ServiceLog log = new ServiceLog();
                JSONObject obj = JSON.parseObject(next.toString());
                JSONObject source = obj.getJSONObject("_source");
                Date dat = source.getDate("@timestamp");
                String filePath =  source.getJSONObject("log").getJSONObject("file").getString("path");
                log.setDate(dat);
                log.setFileName(StringUtils.isNotEmpty(filePath)?filePath.substring(filePath.lastIndexOf("/")):"");
                log.setFilePath(filePath);
                log.setLogs(source.getString("message"));
                log.setOffset(source.getJSONObject("log").getLong("offset"));
                log.setLogLevel(dto.getLogLevel());
                log.setHostName(source.getJSONObject("host").getString("hostname"));
                log.setHostIp(source.getJSONObject("host").getJSONArray("ip").getString(0));
                log.setId(obj.getString("_id"));
                list.add(log);
            }
            System.out.println("==================>");
            System.out.println(list);
            System.out.println("==================>");




////            query(client, dto);
//            queryById(client,"4rbHLXoBfKxgscDx5ulc");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void test(SearchResponse search) {
//        // 解析
        SearchHits hits = search.getHits();
        SearchHit[] hits1 = hits.getHits();
        for (SearchHit hit : hits1) {
//            // 取出source数据
//            String itemstring = hit.getSourceAsString();
//            // 反序列化
//            System.out.println(itemstring);

            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            System.out.println(sourceAsMap);
        }
    }


    public static void put(RestHighLevelClient client) {
        // 文档 Document Id
        IndexRequest request = new IndexRequest("hello", "string", "data");
//        String jsonString = "{" + "\"user\":\"kimchy\"," + "\"postDate\":\"2013-01-30\"," + "\"message\":\"trying out Elasticsearch\"" + "}";
        String jsonString = "{\"code\":0,\"msg\":\"操作成功\",\"data\":{\"id\":217,\"name\":\"lfy\",\"nickName\":\"lfy\",\"roles\":[{\"userId\":217,\"roleId\":1,\"name\":\"管理员\"},{\"userId\":217,\"roleId\":36,\"name\":\"市级管理员\"},{\"userId\":217,\"roleId\":42,\"name\":\"二级管理员\"}],\"roleList\":\"市级管理员,二级管理员,管理员\",\"gmtCreate\":\"2020-09-27T08:34:52.000+0000\",\"loginTime\":\"2021-06-10T07:23:16.000+0000\",\"ip\":\"0:0:0:0:0:0:0:1\",\"defaultClusterId\":70,\"token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJpc3MiOiIyMTciLCJleHAiOjE2MjQxNzM4NDgsImlhdCI6MTYyMzMwOTg0OH0.i3JCccEWc3_NYqJqw0p7t7I5osq0-0zrP0tcOLzK7VEx7BrLyNVR9Pjl4E7HlFGcxVXPIUcujzuh8jcffOePmQ\",\"permsSet\":[\"role\",\"role:update\",\"user:add\",\"user:deletes\",\"role:delete\",\"user:update\",\"user\",\"role:add\",\"role:select\"]}}";
        request.source(jsonString, XContentType.JSON);
        try {
            IndexResponse index1 = client.index(request, RequestOptions.DEFAULT);
            String s = index1.toString();
            System.out.println(s);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void get(RestHighLevelClient client) {
        //查询,  index  type id 为必填字段
        GetRequest get = new GetRequest("hello", "string", "user");
        //是否实时
//        get.realtime(true);
        //不获取源数据  默认获取
//        get.fetchSourceContext(FetchSourceContext.FETCH_SOURCE);
        //排除指定字段
        String[] includes = new String[]{"code"}; // 包括字符串
//        String[] excludes = new String[]{"msg"}; //排除消息
        FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, null);
        get.fetchSourceContext(fetchSourceContext);
        try {
            GetResponse documentFields = client.get(get, RequestOptions.DEFAULT);
            boolean exists = documentFields.isExists();
            if (exists) {
                System.out.println("=============================>");
                System.out.println(documentFields.getSource());
                System.out.println("=============================>");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void search(RestHighLevelClient client) {
        SearchRequest request = new SearchRequest("spring-admin-elasticsearch-info-elasticsearch-info.log");
//        String[] includes = new String[]{"code"}; // 包括字符串
//        String[] excludes = new String[]{"msg"}; //排除消息
        //使用 SearchSourceBuilder 配置参数
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String[] includes = {"input","agent","@timestamp","log","message","host.hostname"};
        String[] execludes = {};
        //包含项和排除项
        searchSourceBuilder.fetchSource(null, execludes);
        //术语匹配查询
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("log.offset", 1023356);
        searchSourceBuilder.query(termQueryBuilder);


        //整合request 与查询
        request.source(searchSourceBuilder);
        //分页查询
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(20);
        //排序
        searchSourceBuilder.sort("@timestamp");
        //使用MatchQueryBuilder配置查询参数
        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("message", "ERROR");
        // 启动模糊查询
        matchQueryBuilder.fuzziness(Fuzziness.AUTO);
        // 在匹配查询上设置前缀长度选项
        matchQueryBuilder.prefixLength(3);
        // 设置最大扩展选项以控制查询的模糊过程
        matchQueryBuilder.maxExpansions(10);
//        searchSourceBuilder.query(matchQueryBuilder);

        //时间范围查询
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        String format1 = format.format(new Date());
        System.out.println(format1);
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("@timestamp");
        rangeQueryBuilder.from("2021-06-16T09:39:59.927Z");
        rangeQueryBuilder.to("2021-06-17T09:39:59.927Z");
//        searchSourceBuilder.query(rangeQueryBuilder);
        try {
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            SearchHits hits = search.getHits();
            if (hits != null) {
                System.out.println("=============================>");
                for (SearchHit hit : hits.getHits()) {
                    System.out.println(hit.toString());
                    JSONObject jsonObject = JSON.parseObject(hit.toString());
                    Object o = jsonObject.getJSONObject("_source").getJSONObject("log").getJSONObject("file").getString("path");
                    System.out.println(o.toString());
                    Date date = jsonObject.getJSONObject("_source").getDate("@timestamp");
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    System.out.println(sdf.format(date));

                }
                System.out.println("=============================>");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询
     *
     * @param dto
     * @return void
     * @author Lin FuYuan
     * @date 2021/6/18
     */
    public static SearchRequest query(RestHighLevelClient client, QueryLogDTO dto) {
        //index;
        String index = "spring-admin-yarn-*";
        //查询请求
        SearchRequest request = new SearchRequest(index);
        //组装查询 -------
        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
        //包含 和排除 的相关字段
        String[] includes = {"input", "@timestamp", "log", "message", "host.hostname"};
        String[] excludes = {"log.flags"};
        searchBuilder.fetchSource(includes, excludes);
        //日期范围查询
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("@timestamp");
        rangeQueryBuilder.from("2021-06-17T09:39:59.927Z");
        rangeQueryBuilder.to("2021-06-22T09:39:59.927Z");
//        rangeQueryBuilder.from(format.format(dto.getStartTime()));
//        rangeQueryBuilder.to(format.format(dto.getEndTime()));
        searchBuilder.query(rangeQueryBuilder);

        //模糊匹配查询
        if (StringUtils.isNotEmpty(dto.getKeyWorld())) {
            MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("message", dto.getKeyWorld());
            matchQueryBuilder.fuzziness(Fuzziness.AUTO);
//            searchBuilder.query(matchQueryBuilder);
        }

        //条件查询
        if (!CollectionUtils.isEmpty(dto.getHostNames())) {
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            for (String hostName : dto.getHostNames()) {
                //包含内容的查询
                boolQuery.must(QueryBuilders.matchQuery("host.hostname", hostName));
            }
            //包含术语的查询
            boolQuery.must(QueryBuilders.termQuery("log.offset", 1311797));
//            searchBuilder.query(boolQuery);
        }

        //分页查询
        int startNum = (dto.getPageNum() - 1) * dto.getPageSize();
//        searchBuilder.from(startNum > 0 ? startNum : 0);
//        searchBuilder.size(dto.getPageSize());
        searchBuilder.trackTotalHits(true);
        //根据日期排序
        searchBuilder.sort("@timestamp", SortOrder.DESC);
        //整合查询条件
        request.source(searchBuilder);

        try {
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            int totalShards = search.getTotalShards();
            System.out.println(totalShards);
            SearchHits hits = search.getHits();
            if (hits != null) {
                System.out.println("=============================>");
                for (SearchHit hit : hits.getHits()) {
                    System.out.println(hit.toString());
                    JSONObject jsonObject = JSON.parseObject(hit.toString());
                    Object o = jsonObject.getJSONObject("_source").getJSONObject("log").getJSONObject("file").getString("path");
                    System.out.println(o.toString());
                }
                System.out.println("=============================>");
            }
            TotalHits totalHits = hits.getTotalHits();
            System.out.println("总数:"+totalHits.value );
        } catch (IOException e) {
            e.printStackTrace();
        }
        return request;
    }


    public static void queryById(RestHighLevelClient client,String id){
        //index;
        String index = "spring-admin-yarn-*";
        SearchRequest request = new SearchRequest(index);
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.matchQuery("_id",id));
        builder.query(boolQuery);
        request.source(builder);
        try {
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
            SearchHits hits = search.getHits();
            if (hits != null) {
                System.out.println("=============================>");
                for (SearchHit hit : hits.getHits()) {
                    JSONObject obj = JSON.parseObject(hit.toString());
                    System.out.println(obj.getString("_id"));
                    System.out.println(hit.toString());
                }
                System.out.println("=============================>");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 查询
     * @author Lin FuYuan
     * @param dto
     * @date 2021/6/18
     * @return void
     */
    private static SearchRequest query(QueryLogDTO dto) {
        //index;
        String index = "spring-admin-"+dto.getServerName()+"-*";
        index = StringUtils.lowerCase(index);
        //查询请求
        SearchRequest request = new SearchRequest(index);
        //组装查询 -------
        SearchSourceBuilder searchBuilder = new SearchSourceBuilder();
        //包含 和排除 的相关字段
        String[] includes = {"input","agent","@timestamp","log","message","host.hostname"};
        String[] excludes = {};
        searchBuilder.fetchSource(includes,excludes);
        //日期范围查询 rangeQuery 比较大小区间查询
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
//        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("@timestamp");
//        rangeQueryBuilder.from(format.format(dto.getStartTime()));
//        rangeQueryBuilder.to(format.format(dto.getEndTime()));
//        searchBuilder.query(rangeQueryBuilder);

        //模糊匹配查询  matchQuery  会分词
        if(StringUtils.isNotEmpty(dto.getKeyWorld())){
            MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("message", dto.getKeyWorld());
            matchQueryBuilder.fuzziness(Fuzziness.AUTO);
            searchBuilder.query(matchQueryBuilder);
        }

        //条件查询 termQuery 不分词     termQuery 详解: http://blog.sina.com.cn/s/blog_7b87efa50102wfxg.html
        if(dto.getHostNames()!=null && dto.getHostNames().size()>0){
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            boolQuery.must(QueryBuilders.termsQuery("host.hostname",dto.getHostNames().toArray()));
            //包含术语的查询
            boolQuery.must(QueryBuilders.termQuery("message",dto.getLogLevel()));
            searchBuilder.query(boolQuery);
        }

        //分页查询
        int startNum = (dto.getPageNum()-1)*dto.getPageSize();
        searchBuilder.from(startNum);
        searchBuilder.size(dto.getPageSize());
        searchBuilder.trackTotalHits(true);
        //整合查询条件
        request.source(searchBuilder);
        return request;
    }


}
